/*********************************************************************
Programmer:     Danny Vargas & Kevin Collins
Date:           04/29/09
File:           Disk.cpp
Description:	[Read Disk.h]
Implementation: [Read Disk.h]
**********************************************************************/

#include <sstream>
#include <iostream>
#include "Disk.h"
using namespace std;

/*********************************************************************
	File Class
**********************************************************************/

File :: File (const string file, string priv)
{
	fileName = file; 
	privilege = priv;
	linePos = 0;
	lineRow = 0;

	string temp = file.substr(file.rfind(".")+1, 4);
	if (temp == "s") fileType = "assembler";
	else if (temp == "o") 
	{ 
		fileType = "object";
		if (priv == "r")
			if (!createIndex())
				cout << "This file contains nothing!\n";
		
	}
	else if (temp == "st") 
	{
		if (priv == "rw" || priv == "rw") fileType = "stack";
		else if (priv == "w") fileType = "istack";
		else fileType = "ostack";
	}
	else if (temp == "out") 
	{
		if (priv == "w") fileType = "out";
		else { fileType = "clear-out"; privilege = "w"; }
	}
	else if (temp == "in") fileType = "in";
	else fileType = "character";

} // File(string, string)

File :: File (const File & source)
{
	fileName = source.fileName;
	privilege = source.privilege;
	fileType = source.fileType;
	linePos = source.linePos;
	lineRow = source.lineRow;
	index = source.index;
} // File(File)

string File :: type () const
{
	return fileType;
} // type

void File :: changePriv (string priv)
{
	privilege = priv;
} // changePriv

void File :: delFile ()
{
	if (fileType != "out" && fileType != "in") remove(fileName.c_str());
} // delFile

bool File :: createIndex()
{
	Disk temp(*this);
	int loc;
	index.push_back(0);
	while(loc = temp.readLine())
		index.push_back(loc);
	return index.size();
} // createIndex

int File :: indexLine(const int line) const
{
	if (index.size())
		return index[line];
	return -1;
} // indexLine

/*********************************************************************
	Disk Class
**********************************************************************/

Disk :: Disk ()
{
	fileType = "none";
} // Disk

Disk :: Disk (string name, string privilege) 
{ 		
	File temp(name, privilege);
	open(temp.fileName, temp.privilege, temp.fileType);
} // Disk(string, string)

Disk :: Disk (const File obj)
{
	open(obj.fileName, obj.privilege, obj.fileType);
} // Disk(File)

Disk :: ~Disk()
{
	if (stream) close();
} // ~Disk

bool Disk :: open (const File obj)
{
	return open(obj.fileName, obj.privilege, obj.fileType);
} // open(File)

bool Disk :: open (string name, string privilege)
{
	return open(File(name, privilege));
} // open(string, string)

bool Disk :: open (string name, string privilege, string type)
{
	fileType = type;

	try {
		if((privilege=="rw") || (privilege=="wr")) {
			stream = new fstream(name.c_str(), fstream::in | fstream::out);
			writeP=true;
			readP=true;
			return true;
		}
		else if(privilege=="r") {
			stream = new fstream(name.c_str(), ios::in);
			writeP=false;
			readP=true;
			return true;
		}
		else if(privilege=="w") {
			if (fileType == "out") stream = new fstream(name.c_str(), ios::out | ios::app);
			else stream = new fstream(name.c_str(), ios::out);
			writeP=true;
			readP=false;
			return true;
		}
		else
			cout <<"Valid file access premission not provide (rw | r | w)\n";
	}
	catch(...) {
		throw;
	}
} // open(string, string, string)

void Disk :: close ()
{
	if ((*stream).is_open()) { 
		delete stream;
		stream=0;
	}
} // close

vector<string> Disk :: getLine () const
{
	return line;
} // getLine

string Disk :: type () const
{
	return fileType;
} // type

void Disk :: setRead (int place)
{
	(*stream).seekg(place);
} // setRead

void Disk :: setWrite (int place)
{
	(*stream).seekp(place);
} // setWrite
	
int Disk :: readLine ()
{
	if(!(*stream).is_open() || (*stream).eof() || writeP)
		return 0;

	line.clear();

	string tempLine, tempParam;

	getline(*stream,tempLine);

	if ((*stream).eof() && !tempLine.size())
		return 0;
	
	if(fileType=="assembler" && tempLine.find(';') != string::npos)
		tempLine.resize(tempLine.find(';'));

	if(tempLine.length() > 0) {
		istringstream str (tempLine.c_str());

		while(str.peek() != -1) {
			tempParam.clear();
			str >> skipws >> tempParam;
			if(tempParam.length())
				line.push_back(tempParam);
		}
	}
	return (*stream).tellg();
} // readLine
